#include "./domain.h"

/**
/*  Implementacao do metodo "set" para os objetos do tipo "String".
*/
inline void StringObject::set(const string& valor) throw (invalid_argument) {
        validate(valor);
        this->value = valor;
}
/**
/*  Implementacao do metodo "get" para os objetos do tipo "String".
*/
inline string StringObject::get() const {
       return value;
}

/**
/*  Implementacao do metodo "set" para os objetos do tipo "Float".
*/
inline void FloatObject::set(const float& valor) throw (invalid_argument) {
        validate(valor);
        this->value = valor;
}
/**
/*  Implementacao do metodo "get" para os objetos do tipo "Float".
*/
inline float FloatObject::get() const {
       return value;
}

/**
/*  Implementacao do metodo "set" para os objetos do tipo "Int".
*/
inline void IntObject::set(const int& valor) throw (invalid_argument) {
        validate(valor);
        this->value = valor;
}
/**
/*  Implementacao do metodo "get" para os objetos do tipo "Int".
*/
inline int IntObject::get() const {
       return value;
}

/**
/*  Implementacao do metodo "validate" para os objetos do tipo "Name".
*/
void Name::validate(string nome) throw (invalid_argument){
    if (nome.size() == 0)
        throw invalid_argument("O nome nao foi informado.\n");
    if (nome.size() > 20)
        throw invalid_argument("O nome possui mais de 20 caracteres.\n");
    for (unsigned int i = 0; i < nome.size(); i++) {
        if (!isspace(nome.at(i)) &&
            !isupper(nome.at(i)) &&
            !islower(nome.at(i)) &&
            nome.at(i)!='.')
                throw invalid_argument("O nome possui caracteres invalidos.\n");
    }
}

/**
/*  Implementacao do metodo "validate" para os objetos do tipo "Password".
*/
void Password::validate(string senha) throw (invalid_argument){
    if (senha.size() == 0)
        throw invalid_argument("Senha nao informada.\n");
    if (senha.size() > 5)
        throw invalid_argument("A senha informada possui mais de 5 caracteres.\n");
}

/**
/*  Implementacao do metodo "validate" para os objetos do tipo "Address".
*/
void Address::validate(string endereco) throw (invalid_argument){
    if (endereco.size() == 0)
        throw invalid_argument("O endereco nao foi informado.\n");
    if (endereco.size() > 30)
        throw invalid_argument("O endereco informado possui mais de 30 caracteres.\n");
}

/**
/*  Implementacao do metodo "validate" para os objetos do tipo "CPF".
*/
void CPF::validate(string cpf) throw (invalid_argument){
    if (cpf.size() != 11)
        throw invalid_argument("O CPF informado nao possui 11 digitos.\n");
    for (unsigned int i = 0; i < cpf.size(); i++) {
        if (!isdigit(cpf.at(i)))
                throw invalid_argument("O CPF possui apenas numeros.\n");
    }
}

/**
/*  Implementacao do metodo "validate" para os objetos do tipo "Price".
*/
void Price::validate(float preco) throw (invalid_argument){
    if (preco < 0.0 || preco > 9999.99)
        throw invalid_argument("O preco nao pode ser maior que $9999.99.\n");
}

/**
/*  Implementacao do metodo "validate" para os objetos do tipo "Identifier".
*/
void Identifier::validate(string identificador) throw (invalid_argument){
    if (identificador.size() == 0)
        throw invalid_argument("O identificador nao foi informado.\n");
    if (identificador.size() > 10)
        throw invalid_argument("O identificador informado possui mais de 10 caracteres.\n");
    for (unsigned int i = 0; i < identificador.size(); i++) {
        if (!isdigit(identificador.at(i)) &&
            !isupper(identificador.at(i)) &&
            !islower(identificador.at(i)))
                throw invalid_argument("O identificador so' pode ser composto por letras e numeros.\n");
    }
}

/**
/*  Implementacao do metodo "validate" para os objetos do tipo "Description".
*/
void Description::validate(string descricao) throw (invalid_argument){
    if (descricao.size() == 0)
        throw invalid_argument("A descricao nao foi informada.\n");
    if (descricao.size() > 50)
        throw invalid_argument("A descricao informada possui mais de 50 caracteres.\n");
}

/**
/*  Implementacao do metodo "validate" para os objetos do tipo "AccessLevel".
*/
void AccessLevel::validate(int nivelacesso) throw (invalid_argument){
    if (nivelacesso != 0 && nivelacesso != 1)
        throw invalid_argument("O nivel de acesso so' pode ser \"0\" (publico) ou \"1\" (privado).\n");
}

/**
/*  Implementacao do metodo "validate" para os objetos do tipo "Quantity".
*/
void Quantity::validate(int quantidade) throw (invalid_argument){
    if (quantidade < 1)
        throw invalid_argument("O pedido deve possuir pelo menos um album.\n");
    if (quantidade > 99)
        throw invalid_argument("O pedido nao pode ter mais de 99 albuns.\n");
}

/**
/*  Implementacao do metodo "validate" para os objetos do tipo "Date".
*/
void Date::validate(string data) throw (invalid_argument){
    if (
            data.size() != 10
        ||
            (
                 !isdigit(data.at(0))
                 && !isdigit(data.at(1))
                 && data.at(2)!='/'
                 && !isdigit(data.at(3))
                 && !isdigit(data.at(4))
                 && data.at(5)!='/'
                 && !isdigit(data.at(6))
                 && !isdigit(data.at(7))
                 && !isdigit(data.at(8))
                 && !isdigit(data.at(9))
             )
        ||
             (
                 (data.at(0) > '4')
                 || ( (data.at(0) > '3') && (data.at(1) > '1') )
                 || (data.at(3) > '2')
                  || ( (data.at(3) > '1') && (data.at(4) > '2') )
             )
        )
        throw invalid_argument("A data informada esta' incorreta.\n");
}

/**
/*  Implementacao do metodo "validate" para os objetos do tipo "Speed".
*/
void Speed::validate(float velocidade) throw (invalid_argument){
        if (
                (velocidade != 1.0)
                && (velocidade != 1./2.)
                && (velocidade != 1./4.)
                && (velocidade != 1./8.)
                && (velocidade != 1./15.)
                && (velocidade != 1./30.)
                && (velocidade != 1./60.)
                && (velocidade != 1./125.)
                && (velocidade != 1./250.)
                && (velocidade != 1./500.)
                && (velocidade != 1./1000.)
            )
            throw invalid_argument("A velocidade do obturador esta' incorreta.\n");
}

/**
/*  Implementacao do metodo "validate" para os objetos do tipo "Openness".
*/
void Openness::validate(float abertura) throw (invalid_argument){
        if (
                (abertura != 1.0)
                && (abertura != 1.4)
                && (abertura != 2.)
                && (abertura != 2.8)
                && (abertura != 4.)
                && (abertura != 5.6)
                && (abertura != 8.)
                && (abertura != 11.)
                && (abertura != 16.)
                && (abertura != 22.)
            )
            throw invalid_argument("A abertura do diafragma esta' incorreta.\n");
}

/**
/*  Implementacao do metodo "validate" para os objetos do tipo "ISO".
*/
void ISO::validate(int iso) throw (invalid_argument){
        if (
                (iso != 80)
                && (iso != 100)
                && (iso != 200)
                && (iso != 400)
                && (iso != 800)
                && (iso != 1600)
            )
            throw invalid_argument("O parametro \"ISO\" esta' incorreto.\n");
}

/**
/*  Implementacao do metodo "validate" para os objetos do tipo "Status".
*/
void Status::validate(int status) throw (invalid_argument){

        if (status != 0 && status != 1)
        throw invalid_argument("O status do pedido so' pode ser \"0\" (pendente) ou \"1\" (concluido).\n");
}
